﻿#include "login.h"
#include "ui_login.h"
#include <QJsonDocument>
#include <QJsonArray>
#include <QJsonObject>
#include <QJsonParseError>
#include <QMessageBox>
#include <QApplication>
#include <QFile>
#include <QtXml>

Login::Login(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Login),
    signup(new SignUp),
    chatroom(new ChatRoom)
{
    ui->setupUi(this);

    socket = new QTcpSocket(this);

    // 当前可执行程序所在的路径
    QString path = QCoreApplication::applicationDirPath();
    QFile file(path + "/xml.xml");
    if (!file.open(QIODevice::ReadOnly))
    {
        qDebug() << "文件打开失败!" << file.errorString() << endl;
        return;
    }

    QByteArray content = file.readAll();
    file.close();

    QDomDocument doc; // xml文件对象
    QString errorString;
    int row, col;
    if (doc.setContent(content, &errorString, &row, &col) == false)
    {
        qDebug() << row << ", " << col << errorString << endl;
        return;
    }
    qDebug() << "xml打开成功!" << endl;

    QDomElement root = doc.documentElement(); // 根节点
    qDebug() << root.nodeName() << endl;

    auto sqlName = root.firstChildElement("服务器"); // 取子节点中名字是服务器的
    qDebug() << sqlName.attributeNode("host").value() << endl;; // 取服务器的属性节点

    // 连接服务器
    socket->connectToHost(sqlName.attributeNode("host").value(), 8080);

    connect(socket,&QTcpSocket::connected,[]()
    {
        qDebug()<<"连接成功!\n";
    });

    connect(this, &Login::transfer, signup, &SignUp::GetSocket); // 传递sock套接字
    connect(signup, &SignUp::GoBack, this, &Login::ShowLoginFace); // 注册页面返回登录界面

    // 准备读写
    connect(this->socket, &QTcpSocket::readyRead, this, &Login::ReadData);

    connect(chatroom, &ChatRoom::ExitChat, this, &Login::ExitChat);

    connect(this, &Login::sendFromName, chatroom, &ChatRoom::GetFromName);
    connect(this, &Login::SetSocket, chatroom, &ChatRoom::GetSocket); // 传递sock套接字
}

Login::~Login()
{
    delete ui;
}

void Login::process(const QByteArray &data)
{
    auto obj = QJsonDocument::fromJson(data).object(); // 解析Json数据，允许访问Json数据中的各个字段
    qDebug() << "login.cpp处理json逻辑:" << QJsonDocument(obj).toJson() << endl;

    if(obj["result"].toInt() == 0) // 如果Json数据中包含"result"字段且其值为0，则认为发生了错误
    {
        QMessageBox::information(this,"error",obj["msg"].toString()); // 弹出一个信息框显示具体的错误消息("msg"字段)
        return;
    }

    if (obj["request"] == "SIGNUP")
    {
        signup->process(data);
    }

    if(obj["request"] == "LOGIN") // 请求类型为"LOGIN"时，表示需要注册
    {
        if(obj["msg"] == "success")
        {
            QMessageBox::information(this,"提示", "登录成功!"); // 弹出一个信息框显示具体的错误消息("msg"字段)
            chatroom->show();
            emit sendFromName(ui->lineEdit_account->text());
            emit SetSocket(socket);
            this->hide();
            ui->lineEdit_passwd->clear();
            ui->lineEdit_account->clear();
            return;
        }
        else if(obj["msg"] == "password error")
        {
            QMessageBox::information(this,"提示", "密码错误，登录失败!"); // 弹出一个信息框显示具体的错误消息("msg"字段)
            return;
        }
        else if(obj["msg"] == "user does not exist")
        {
            QMessageBox::information(this,"提示", "用户名不存在，请稍后再试!"); // 弹出一个信息框显示具体的错误消息("msg"字段)
            return;
        }
    }

    if (obj["request"] == "ONLINELIST")
    {
        chatroom->process(data);
    }
}

void Login::WriteToServer(const QJsonObject &obj)
{
    // 将QJsonObject包装成一个QJsonDocument对象,并将QJsonDocument转换为JSON格式的QByteArray
    auto data = QJsonDocument(obj).toJson();
    int size =  data.size(); // 获取数据(data)的长度
    socket->write((char*)&size,sizeof(int)); // 将数据长度写入套接字(告诉接收方数据多长)
    socket->write(data); // 将Json数据写入套接字
}

// 点击注册按钮
void Login::on_pushButton_signup_clicked()
{
    this->hide();
    signup->show();
    emit transfer(socket);
}

// 显示登录界面
void Login::ShowLoginFace()
{
    signup->hide();
    this->show();
}

// 点击登录按钮
void Login::on_pushButton_login_clicked()
{
    qDebug() << "点击确定按钮" << endl;
    auto account = ui->lineEdit_account->text(); // 获取用户输入的账号
    auto passwd = ui->lineEdit_passwd->text(); // 获取用户输入的密码
    QJsonObject obj; // 构建Json对象
    obj["request"] = "LOGIN"; // 请求类型为LOGIN
    obj["account"] = account; // 用户的账号
    obj["passwd"] = passwd; // 用户的密码
    WriteToServer(obj); // 发送到服务器
}

void Login::ReadData()
{
    buffer += socket->readAll(); // 读取tcp缓冲区的所有数据
    while(buffer.size() >= sizeof(int)) // 读取的数据长度大于包头长度，说明有需要的数据
    {
        int size = 0;
        memcpy(&size, buffer.data(), sizeof(int)); // json包的大小
        if( buffer.size() < size + sizeof(int)) // buffer中的数据不够读一包json
        {
            return;
        }

        QByteArray data = buffer.mid(sizeof(int), size); // 一包json数据
        buffer.remove(0, size + sizeof(int)); // 删去已经读取过的数据
        process(data); // 处理json逻辑
    }
}

void Login::ExitChat()
{
    chatroom->hide();
    this->show();
}
